function TLSyncDlg(varargin)

% TL_SYNC_SYSTEM_DLG creates and manages Synchronize System dialog
%
% SYNTAX TLSyncDlg('Create', options)
%   create dialog , or move to foreground
%
%   INPUT ARGUMENTS
%   options       structure with options
%
%   OUTPUT ARGUMENTS
%     - / -
%
% SYNTAX TLSyncDlg('Callback', controlName, dlgfig)
%   manage callback of user interface control
%
%   INPUT ARGUMENTS
%   dlgfig        figure handle of dialog
%   controlName   name of control triggered the callback
%
%   OUTPUT ARGUMENTS
%     - / -
%
% See also tl_sync_system


% Author(s): C. Witte
% $RCSfile: TLSyncDlg.m $
% $ProjectName: e:/ARC/Components/HostSW/ProdCodeGen/ModelPreparator/Sources/MSrc/project.pj $
% $Revision: 1.11 $
% $Date: 2011/03/11 09:21:57MEZ $
%
% Copyright ?2010 dSPACE GmbH. All rights reserved.

% open dial
if nargin == 0
    tl_sync_system;
    return;
end

Action = varargin{1};
switch Action
    case 'create'
        %*****************************************************************************
        % Create the dialog, or shove it into the foreground if a dialog already exists .
        %*****************************************************************************

        dlgfigs = ds_find_dialogs('TargetLink Model Synchronization Dialog');
        
        % delete all but one - makes things a little more robust
        for i=2:numel(dlgfigs)
            delete(dlgfigs(i));
        end
        if ~isempty(dlgfigs)
            figure(dlgfigs(1));
            return;
        end
        FcnCreate(varargin{2});

        %*****************************************************************************
        % A control has been hit.
        %*****************************************************************************
    case 'callback'
        dlgfig = varargin{2};
        dlgdata = get(dlgfig,'UserData');
        FcnManageControls(dlgfig,dlgdata,varargin{3});
end


%================================================================================
%
% Function creates the dialog.  
% 
% Input parameters
%   options   model preparation options struct
%
%================================================================================
function FcnCreate(options)

% get global TargetLink options and block data

dlgfig = figure( ...
    'DefaultUicontrolHorizontalAlign',   'left',...
    'Visible',                           'off',...
    'DefaultUicontrolUnits',             'pixels',...
    'DefaultUicontrolInterruptible',     'off',...
    'HandleVisibility',                  'off',...
    'Colormap',                          [],...
    'Toolbar',                           'none', ...
    'MenuBar',                           'none', ...
    'DockControls',                      'off', ...
    'NumberTitle',                       'off', ...
    'Name',                              'System Synchronization',...
    'IntegerHandle',                     'off',...
    'Interruptible',                     'off',...
    'Tag',                               'TargetLink Model Synchronization Dialog', ...
    'BusyAction',                        'queue',...
    'Color',                             get(0,'DefaultuicontrolBackGroundColor'), ...
    'KeyPressFcn',                       ' ',...
    'CloseRequestFcn',                   'TLSyncDlg(''callback'',gcbf,''Close'')');

% Construct common geometry constants.

commonGeom = ds_get_common_geometry;
set(dlgfig,...
    'DefaultUicontrolFontname',commonGeom.fontname,...
    'DefaultUicontrolFontsize',commonGeom.fontsize);

% now create the controls these are the strings
strings_and_styles = {...
    'Process related user libraries',     'checkbox'; ...
    'Sync output scaling data',           'checkbox'; ...
    'Sync signal scaling data',           'checkbox'; ...
    'Sync parameter scaling data',        'checkbox'; ...
    'Sync RTW data',                      'checkbox'; ...
    'Verbose output',                     'checkbox'; ...
    'Synchronize System',                 'pushbutton'; ...
    ' Edit ',                             'pushbutton'; ...
    'Open system from file ...',           'pushbutton'; ...
    'Select current subsystem',           'pushbutton'; ...
    'Synchronize Library',                'pushbutton'; ...
    'Sync Stateflow scaling data',        'checkbox'; ...
    'Sync Stateflow compiled scaling data', 'checkbox'; ...
    'Simulink to TargetLink',             'radiobutton'; ...
    'TargetLink to Simulink',             'radiobutton'; ...
    'Sync saturation flags',              'checkbox'; ...
    'Sync constrained limits',            'checkbox'};

% ... and the sizes.
[ ...
    syncLibsCheckboxSize, ...
    syncOutputScalingDataCheckboxSize, ...
    syncSignalScalingDataCheckboxSize, ...
    syncParameterScalingDataCheckboxSize, ...
    syncRTWDataCheckboxSize, ...
    verboseCheckboxSize, ...
    syncSystemButtonSize, ...
    editLogfileButtonSize, ...
    browseButtonSize, ...
    selectButtonSize, ...
    syncLibButtonSize, ...
    syncSFScalingDataCheckboxSize, ...
    syncSFCompiledDataCheckboxSize, ...
    SL2TLRadiobuttonSize, ...
    TL2SLRadiobuttonSize, ...
    syncSaturationFlagsCheckboxSize, ...
    syncConstrainedLimitsCheckboxSize] ...
    = ds_get_uicontrol_sizes(commonGeom,strings_and_styles); %#ok

% calculate widths of columns
widths = [ ...
    max([ ...
    syncOutputScalingDataCheckboxSize(1) ...
    syncSignalScalingDataCheckboxSize(1) ...
    syncParameterScalingDataCheckboxSize(1) ...
    syncRTWDataCheckboxSize(1) ...
    SL2TLRadiobuttonSize(1)]) ...
    5+max([ ...
    syncSFScalingDataCheckboxSize(1) ...
    syncSFCompiledDataCheckboxSize(1) ...
    syncLibsCheckboxSize(1) ...
    verboseCheckboxSize(1) ...
    TL2SLRadiobuttonSize(1)])];
[col,colWidth,colDelta,rowDelta] = ds_get_gui_columns(widths,commonGeom);

systemGroupboxWidth = col(end) + ...
    colWidth(end) + ...
    commonGeom.frameSideEdgeBuffer;

systemGroupboxHeight = ...
    commonGeom.frameTopEdgeBuffer + ...
    8 * rowDelta + ...
    8 * commonGeom.editHeight + ...
    commonGeom.frameBottomEdgeBuffer;
systemEditSize = [colWidth(1)+colWidth(2)-colDelta-syncSystemButtonSize(1) commonGeom.editHeight];

libGroupboxWidth  = systemGroupboxWidth;
libGroupboxHeight = ...
    commonGeom.frameTopEdgeBuffer + ...
    4 * rowDelta + ...
    5 * commonGeom.editHeight + ...
    commonGeom.frameBottomEdgeBuffer;

logFileGroupboxWidth = systemGroupboxWidth;
logFileGroupboxHeight = ...
    commonGeom.frameTopEdgeBuffer + ...
    0 * rowDelta + ...
    1 * commonGeom.editHeight + ...
    commonGeom.frameBottomEdgeBuffer;
logfileEditSize = systemEditSize;


% start creating the controls from the bottom up
offsets = [
    commonGeom.figSideEdgeBuffer
    commonGeom.figTopEdgeBuffer
    commonGeom.figSideEdgeBuffer
    commonGeom.bottomSheetOffset];

dlgdata.options = options;
dlgdata.prevSystem = '';

%
% Groupbox for logfile
%
cx = commonGeom.figSideEdgeBuffer + commonGeom.sheetSideEdgeBuffer;
cy = commonGeom.bottomSheetOffset + ...
    commonGeom.sheetBottomEdgeBuffer;
logFileGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Logfile'}, ...
    'Units',            'pixels', ...
    'Position',          [cx cy logFileGroupboxWidth logFileGroupboxHeight]);

%
% log file edit control
%
cx = col(1);
cy = commonGeom.frameBottomEdgeBuffer;
Children.logfileEdit = uicontrol( ...
    'Parent',             logFileGroupbox, ...
    'ToolTipString',      'File to which preparation messages should be appended', ...
    'BackGroundColor',    'w', ...
    'Style',              'edit', ...
    'Position',           [cx cy logfileEditSize]);

%
% edit logfile button
%
cx = cx + logFileGroupboxWidth - 2*commonGeom.frameSideEdgeBuffer - syncSystemButtonSize(1);
Children.logfileButton = uicontrol( ...
    'Parent',             logFileGroupbox, ...
    'ToolTipString',      'Open logfile in Matlab Editor', ...
    'Style',              'pushbutton', ...
    'String',             strings_and_styles{8,1}, ...
    'Position',           [cx cy syncSystemButtonSize]);

%
% Groupbox for related libraries
%
cx = commonGeom.figSideEdgeBuffer + commonGeom.sheetSideEdgeBuffer;
cy = commonGeom.bottomSheetOffset ...
    + commonGeom.sheetBottomEdgeBuffer ...
    + logFileGroupboxHeight ...
    + commonGeom.textHeight;
libGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Related user libraries'}, ...
    'Units',            'pixels', ...
    'Position',          [cx cy libGroupboxWidth libGroupboxHeight]);

%
% verbose checkbox (library)
%
cx = col(2);
cy = commonGeom.frameBottomEdgeBuffer;
Children.verboseLibCheckbox = uicontrol( ...
    'Parent',             libGroupbox, ...
    'Style',              'checkbox', ...
    'ToolTipString',      'Verbose output in Matlab Command Window when library is being prepared', ...
    'String',             strings_and_styles{6,1}, ...
    'Position',           [cx cy verboseCheckboxSize]);

%
% sync constrained limits (library) checkbox
%
cx = col(1);
cy = cy + commonGeom.editHeight + rowDelta;
Children.syncLibConstrainedLimitsCheckbox = uicontrol( ...
    'Parent',             libGroupbox, ...
    'ToolTipString',      'Sync OutMin and OutMax parameters and output.min and output.max properties', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{17,1}, ...
    'Position',           [cx cy syncConstrainedLimitsCheckboxSize]);

%
% map RTW data (library) checkbox
%
cx = col(2);
Children.syncLibRTWDataCheckbox = uicontrol( ...
    'Parent',             libGroupbox, ...
    'ToolTipString',      'Map Simulink RTW parameters to TargetLink properties', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{5,1}, ...
    'Position',           [cx cy syncRTWDataCheckboxSize]);

%
% sync saturation flags checkbox (library)
%
cx = col(1);
cy = cy + commonGeom.editHeight + rowDelta;
Children.syncLibSaturationFlagsCheckbox = uicontrol( ...
    'Parent',             libGroupbox, ...
    'ToolTipString',      'Sync SaturateOnIntegerOverflow parameter and output.checkmin and output.checkmax properties', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{16,1}, ...
    'Position',           [cx cy syncSaturationFlagsCheckboxSize]);

%
% sync parameter scaling checkbox (library)
%
cx = col(2);
Children.syncLibParameterScalingDataCheckbox = uicontrol( ...
    'Parent',             libGroupbox, ...
    'ToolTipString',      'Map Simulink parameter scaling to TargetLink properties', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{4,1}, ...
    'Position',           [cx cy syncParameterScalingDataCheckboxSize]); 

%
% map output scaling data checkbox (library)
%
cx = col(1);
cy = cy + commonGeom.editHeight + rowDelta;
Children.syncLibOutputScalingDataCheckbox = uicontrol( ...
    'Parent',             libGroupbox, ...
    'ToolTipString',      'Sync Simulink local output scaling and TargetLink properties', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{2,1}, ...
    'Position',           [cx cy syncOutputScalingDataCheckboxSize]);

%
% sync SF scaling data checkbox (library)
%
cx = col(2);
Children.syncLibSFScalingDataCheckbox = uicontrol( ...
    'Parent',             libGroupbox, ...
    'ToolTipString',      'Sync Stateflow scaling parameters and TargetLink properties', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{12,1}, ...
    'Position',           [cx cy syncSFScalingDataCheckboxSize]);

%
% related user libraries popupmenu
%
cx = col(1);
cy = cy + commonGeom.editHeight + rowDelta;
Children.userLibsPopup = uicontrol( ...
    'Parent',             libGroupbox, ...
    'ToolTipString',      'Select related user library', ...
    'String',             '(none)', ...
    'BackGroundColor',    'w', ...
    'Style',              'popupmenu', ...
    'Position',           [cx cy systemEditSize]);

%
% sync library button
%
cx = col(2) + colWidth(2) - syncSystemButtonSize(1);
Children.syncLibraryButton = uicontrol( ...
    'Parent',             libGroupbox, ...
    'ToolTipString',      'Synchronize user library', ...
    'Style',              'pushbutton', ...
    'String',             strings_and_styles{11,1}, ...
    'Position',           [cx cy syncSystemButtonSize]);

%
% Groupbox for selected system
%
cx = commonGeom.figSideEdgeBuffer + commonGeom.sheetSideEdgeBuffer;
cy = cy + commonGeom.frameTopEdgeBuffer + 2*commonGeom.editHeight + rowDelta;
cy = commonGeom.bottomSheetOffset ...
    + commonGeom.sheetBottomEdgeBuffer ...
    + libGroupboxHeight ...
    + commonGeom.textHeight ...
    + logFileGroupboxHeight ...
    + commonGeom.textHeight;
systemGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'System'}, ...
    'Units',            'pixels', ...
    'Position',          [cx cy systemGroupboxWidth systemGroupboxHeight]);

%
% map parameter scaling data checkbox
%
cx = col(1);
cy = commonGeom.frameBottomEdgeBuffer;
Children.syncParameterScalingDataCheckbox = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Map Simulink parameter scaling to TargetLink properties', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{4,1}, ...
    'Position',           [cx cy syncParameterScalingDataCheckboxSize]);

%
% verbose checkbox
%
cx = col(2);
Children.verboseCheckbox = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Verbose output in Matlab Command Window when system is being prepared', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{6,1}, ...
    'Position',           [cx cy verboseCheckboxSize]);

%
% map signal scaling data checkbox
%
cx = col(1);
cy = cy + commonGeom.editHeight + rowDelta;
Children.syncSignalScalingDataCheckbox = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Map Simulink signal scaling to TargetLink properties', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{3,1}, ...
    'Position',           [cx cy syncSignalScalingDataCheckboxSize]);

%
% synchronize related user libraries checkbox
%
cx = col(2);
Children.syncLibsCheckbox = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Synchronize related user libraries', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{1,1}, ...
    'Position',           [cx cy syncLibsCheckboxSize]);

%
% sync constrained limits checkbox
%
cx = col(1);
cy = cy + commonGeom.editHeight + rowDelta;
Children.syncConstrainedLimitsCheckbox = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Sync OutMin and OutMax parameters and output.min and output.max properties', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{17,1}, ...
    'Position',           [cx cy syncConstrainedLimitsCheckboxSize]);


%
% map SF compiled data types checkbox
%
cx = col(2);
Children.syncSFCompiledDataCheckbox = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Map Stateflow compiled data types to TargetLink properties', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{13,1}, ...
    'Position',           [cx cy syncSFCompiledDataCheckboxSize]);

%
% sync saturation flags checkbox
%
cx = col(1);
cy = cy + commonGeom.editHeight + rowDelta;
Children.syncSaturationFlagsCheckbox = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Sync SaturateOnIntegerOverflow parameter and output.checkmin and output.checkmax properties', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{16,1}, ...
    'Position',           [cx cy syncSaturationFlagsCheckboxSize]);

%
%  map SF scaling data checkbox
%
cx = col(2);
Children.syncSFScalingDataCheckbox = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Sync Stateflow scaling parameters and TargetLink properties', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{12,1}, ...
    'Position',           [cx cy syncSFScalingDataCheckboxSize]);

%
% map output scaling checkbox
%
cx = col(1);
cy = cy + commonGeom.editHeight + rowDelta;
Children.syncOutputScalingDataCheckbox = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Sync Simulink local output scaling and TargetLink properties', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{2,1}, ...
    'Position',           [cx cy syncOutputScalingDataCheckboxSize]);

%
% map RTW data checkbox
%
cx = col(2);
Children.syncRTWDataCheckbox = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Map Simulink RTW parameters to TargetLink properties', ...
    'Style',              'checkbox', ...
    'String',             strings_and_styles{5,1}, ...
    'Position',           [cx cy syncRTWDataCheckboxSize]);

%
% Simulink to TargetLink radiobutton
% 
cx = col(1);
cy = cy + commonGeom.editHeight + 2* rowDelta;
Children.SL2TLRadiobutton = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Synchronize TargetLink properties with Simulink parameters', ...
    'Style',              'radiobutton', ...
    'String',             strings_and_styles{14,1}, ...
    'Position',           [cx cy SL2TLRadiobuttonSize]);

%
% TargetLink to Simulink radiobutton
% 
cx = col(2);
Children.TL2SLRadiobutton = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Synchronize Simulink parameters with TargetLink properties', ...
    'Style',              'radiobutton', ...
    'String',             strings_and_styles{15,1}, ...
    'Position',           [cx cy TL2SLRadiobuttonSize]);

%
% system edit control
%
cx = col(1);
cy = cy + commonGeom.editHeight + rowDelta;
Children.systemEdit = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Enter name of model, library, or subsystem which should be prepared', ...
    'BackGroundColor',    'w', ...
    'Style',              'edit', ...
    'Position',           [cx cy  systemEditSize]);

%
% sync system button
%
cx = col(2) + colWidth(2) - syncSystemButtonSize(1);
Children.syncSystemButton = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Start synchronization', ...
    'Style',              'pushbutton', ...
    'String',             strings_and_styles{7,1}, ...
    'Position',           [cx cy syncSystemButtonSize(1) 2*syncSystemButtonSize(2)+rowDelta]);

%
% select current subsystem button
%
cx = col(1);
cy = cy + commonGeom.editHeight + rowDelta;
Children.selectButton = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Select current block', ...
    'String',             strings_and_styles{10,1}, ...
    'Style',              'pushbutton', ...
    'Position',           [cx cy  selectButtonSize]);

%
% browse button
%
cx = cx + selectButtonSize(1)+colDelta/3 ;
Children.browseButton = uicontrol( ...
    'Parent',             systemGroupbox, ...
    'ToolTipString',      'Open file dialog to select a Simulink model, or library', ...
    'Style',              'pushbutton', ...
    'String',             strings_and_styles{9,1}, ...
    'Position',           [cx cy browseButtonSize]);

dlgdata.children = Children;
width = ...
    2*commonGeom.frameSideEdgeBuffer + ...
    systemGroupboxWidth;

height = ...
    systemGroupboxHeight + ...
    libGroupboxHeight + ...
    logFileGroupboxHeight + ...
    2*commonGeom.textHeight;

sheetDims = [width height];
commonGeom.sheetPos = [
    offsets(1) + 1
    offsets(4) + 1
    sheetDims(1)
    sheetDims(2)
    ];
figPos = get(dlgfig,'Position');
figHeight = offsets(4) + ...  % bottom offset plus
    sheetDims(2) + ...        % height of sheet plus
    offsets(2) + ...          % top offset plus
    commonGeom.editHeight;    % status label
figWidth = offsets(1) + sheetDims(1) + offsets(3);

figPos(3:4) = [figWidth, figHeight];
screensize = get(0,'ScreenSize');
if figPos(1) + figPos(3) > screensize(3)
    figPos(1) = screensize(3) - figPos(3) - 20;
end
if figPos(2) + figPos(4) + 50 > screensize(4)
    figPos(2) = screensize(4) - figPos(4) - 50;
end

set(dlgfig,'Position',figPos);

% Create system buttons

dlgdata = ...
    FcnCreateSysButtons(dlgfig,dlgdata,commonGeom);

% set callbacks
children = struct2cell(dlgdata.children);
children = [children{:}];
fields = fieldnames(dlgdata.children);
for i=1:numel(children)
    if strcmp(get(children(i), 'Type'), 'uipushtool')
        set(children(i),'ClickedCallback',['TLSyncDlg(''callback'',gcbf,''' fields{i} ''');']);
    else
        set(children(i),'callback',['TLSyncDlg(''callback'',gcbf,''' fields{i} ''');']);
    end
end

%******************************************************************************
% Update user data.
%******************************************************************************
dlgdata.libOptions                = options;
dlgdata.userLibs                  = {};
dlgdata.bHasSFDataObjects         = 1;
FcnUpdate(dlgfig,dlgdata);

% make visible
set(dlgfig,'DefaultUicontrolVisible','on','Visible','on');


%================================================================================
%
% Function - Create system buttons.
%
%================================================================================
function dlgdata = FcnCreateSysButtons(dlgfig,dlgdata,commonGeom)

figPos      = get(dlgfig,'Position');
sheetPos    = commonGeom.sheetPos;
width       = commonGeom.sysButtonWidth;
height      = commonGeom.sysButtonHeight;
buttonDelta = commonGeom.sysButtonDelta;
Children = dlgdata.children;

%******************************************************************************
% Place dSPACE logo
%******************************************************************************
cx = sheetPos(1)+ buttonDelta;
cy = commonGeom.figBottomEdgeBuffer + commonGeom.sysButton_SheetDelta;
ds_create_logo(dlgfig,cx,cy);

%******************************************************************************
% Place apply button.
%******************************************************************************
totalButtonWidth = (width * 2) + (buttonDelta * 1);
sheetEdge = sheetPos(1) + sheetPos(3);

cx = sheetEdge - totalButtonWidth;
cy = commonGeom.figBottomEdgeBuffer;

%******************************************************************************
% Place ok button.
%******************************************************************************
Children.Close = uicontrol( ...
    'Parent',            dlgfig,...
    'ToolTipString',     'Close dialog',...
    'String',            'Close',...
    'Horizontalalign',   'center',...
    'Position',          [cx cy width height]);


%******************************************************************************
% Place help button.
%******************************************************************************
cx = cx + width + buttonDelta;
Children.Help = uicontrol( ...
    'Parent',            dlgfig,...
    'ToolTipString',     'Open associated help document',...
    'String',            'Help',...
    'Enable',            'on',...
    'Horizontalalign',   'center',...
    'Position',          [cx cy width height]);


%******************************************************************************
% Place toolbar icons
%******************************************************************************
hToolbar = uitoolbar(dlgfig);
defaultColor = get(0,'DefaultUicontrolBackgroundColor');

%******************************************************************************
% Place Data Dictionary Manager button.
%******************************************************************************
cData = tl_get_icon('DDMan_20x20', 'BackgroundColor', defaultColor);
hPushbutton = uipushtool(hToolbar,'CData',cData, 'Separator', 'on');
set(hPushbutton, 'Enable', 'on');
Children.Dsddman = hPushbutton;


%******************************************************************************
% Place Property Manager button.
%******************************************************************************
cData = tl_get_icon('PropMan_20x20', 'BackgroundColor', defaultColor);
hPushbutton = uipushtool(hToolbar,'CData',cData);
set(hPushbutton, 'Enable', 'on');
Children.Propman = hPushbutton;


%******************************************************************************
% Place show message browser button.
%******************************************************************************
cData = tl_get_icon('MsgBrowser_20x20', 'BackgroundColor', defaultColor);
hPushbutton = uipushtool(hToolbar,'CData',cData);
set(hPushbutton, 'Enable', 'on');
Children.ShowBrowser = hPushbutton;


%******************************************************************************
% Place status label.
%******************************************************************************
cx = commonGeom.figSideEdgeBuffer;
cy = commonGeom.sysButton_SheetDelta;
Children.StatusLabel = uicontrol( ...
    'Parent',            dlgfig,...
    'Style',             'text', ...
    'Horizontalalign',   'left',...
    'Position',          [cx cy figPos(3)-2*commonGeom.figSideEdgeBuffer commonGeom.textHeight]);

dlgdata.children = Children;


%================================================================================
%
% Function - Manage callbacks for controls
%
% Input parameters
%   dlgfig    dialog figure handle
%   dlgdata   dialog user data
%   Action    name of control = name of field in dlgdata.children struct
%
%================================================================================
function FcnManageControls(dlgfig,dlgdata,Action)

bModified = 0;
options    = dlgdata.options;
libOptions = dlgdata.libOptions;
Children = dlgdata.children;

switch Action
    case 'logfileEdit'
        options.logFileName = deblank(get(Children.logfileEdit,'String'));
        bModified = 1;
    case 'logfileButton'
        edit(options.logFileName);
    case 'syncUserLibsCheckbox'
        options.bSyncLibs = get(Children.syncUserLibsCheckbox,'Value');
        bModified = 1;
    case 'verboseCheckbox'
        options.bVerbose = get(Children.verboseCheckbox,'Value');
        bModified = 1;
    case 'verboseLibCheckbox'
        libOptions.bVerbose = get(Children.verboseLibCheckbox,'Value');
        bModified = 1;
    case 'syncOutputScalingDataCheckbox'
        options.bSyncOutputScalingData = get(Children.syncOutputScalingDataCheckbox,'Value');
        bModified = 1;
    case 'syncLibOutputScalingDataCheckbox'
        libOptions.bSyncOutputScalingData = get(Children.syncLibOutputScalingDataCheckbox,'Value');
        bModified = 1;
    case 'syncSaturationFlagsCheckbox'
        options.bSyncSaturationFlags = get(Children.syncSaturationFlagsCheckbox,'Value');
        bModified = 1;
    case 'syncConstrainedLimitsCheckbox'
        options.bSyncConstrainedLimits = get(Children.syncConstrainedLimitsCheckbox,'Value');
        bModified = 1;
    case 'syncLibConstrainedLimitsCheckbox'
        libOptions.bSyncConstrainedLimits = get(Children.syncLibConstrainedLimitsCheckbox,'Value');
        bModified = 1;
    case 'syncLibSaturationFlagsCheckbox'
        libOptions.bSyncSaturationFlags = get(Children.syncLibSaturationFlagsCheckbox,'Value');
        bModified = 1;
    case 'syncParameterScalingDataCheckbox'
        options.bSyncParameterScalingData = get(Children.syncParameterScalingDataCheckbox,'Value');
        bModified = 1;
    case 'syncLibParameterScalingDataCheckbox'
        libOptions.bSyncParameterScalingData = get(Children.syncLibParameterScalingDataCheckbox,'Value');
        bModified = 1;
    case 'syncLibSFScalingDataCheckbox'
        libOptions.bSyncSFObjectScalingData = get(Children.syncLibSFScalingDataCheckbox,'Value');
        bModified = 1;
    case 'syncRTWDataCheckbox'
        options.bSyncRTWData = get(Children.syncRTWDataCheckbox,'Value');
        bModified = 1;
    case 'syncSFCompiledDataCheckbox'
        options.bSyncSFObjectCompiledScalingData = get(Children.syncSFCompiledDataCheckbox,'Value');
        bModified = 1;
    case 'syncSFScalingDataCheckbox'
        options.bSyncSFObjectScalingData = get(Children.syncSFScalingDataCheckbox,'Value');
        bModified = 1;
    case 'syncLibRTWDataCheckbox'
        libOptions.bSyncRTWData = get(Children.syncLibRTWDataCheckbox,'Value');
        bModified = 1;
    case 'syncSignalScalingDataCheckbox'
        options.bSyncSignalScalingData = get(Children.syncSignalScalingDataCheckbox,'Value');
        bModified = 1;
    case 'syncLibsCheckbox'
        options.bSyncLibs = get(Children.syncLibsCheckbox,'Value');
        bModified = 1;
    case 'syncLibraryButton'
        libOptions.system = dlgdata.userLibs{get(Children.userLibsPopup,'Value')};
        FcnSync(dlgfig,dlgdata,libOptions,0);
    case 'syncSystemButton'
        FcnSync(dlgfig,dlgdata,options,1);
    case 'systemEdit'
        dlgdata.prevSystem = options.system;
        options.system = deblank(get(Children.systemEdit,'String'));
        bModified = 1;
    case 'SL2TLRadiobutton'
        options.bTL2SL = 0;
        bModified = 1;
    case 'TL2SLRadiobutton'
        options.bTL2SL = 1;
        bModified = 1;
    case 'selectButton'
        curSys = gcb;
        if isempty(curSys) || any(strcmp(bdroot(curSys),tl_get_internal_libs))
            ds_error_msg( ...
                'Currently there is no Simulink block selected.', ...
                'Title','Can not select Subsystem', ...
                'PrintMessage','no', ...
                'RegisterMessage', 'no');
        else
            blockType = get_param(curSys,'BlockType');
            if ~strcmp(blockType,'SubSystem')
                ds_error_msg( ...
                    ['The currently selected block is a ' blockType ' block.  Only subsystem blocks can be prepared.'], ...
                    'Title','Not a subsystem', ...
                    'PrintMessage','no', ...
                    'RegisterMessage', 'no');
            else
                options.system = curSys;
                bModified = 1;
            end
        end
    case 'browseButton'
        [options.system,bModified] = FcnBrowse;

    case {'Close','Cancel','CloseReq'}
        set(dlgfig,'Visible','off');
        delete(dlgfig);

    case 'Propman'
        tl_propman(bdroot(dlgdata.options.system));

    case 'Dsddman'
        dsddman;

    case 'Help',
        tl_online_help('topic',mfilename);

    case 'ShowBrowser'
        if isempty(ds_msgdlg('Show'))
            ds_msgdlg('Update');
        end

    otherwise
        error(['Invalid action ' Action]);

end

if bModified
    dlgdata.options    = options;
    dlgdata.libOptions = libOptions;
    FcnUpdate(dlgfig,dlgdata);
end


%================================================================================
%
% Function updates controls and checks options.
%
% Input parameters
%   dlgfig    dialog figure handle
%   dlgdata   dialog user data
%================================================================================
function FcnUpdate(dlgfig,dlgdata)

set(dlgfig,'Pointer','watch');

Children   = dlgdata.children;
options    = dlgdata.options;
libOptions = dlgdata.libOptions;

bSyncSignalDataEnable = ~options.bTL2SL;
bSyncEnable       = 1;
bIsTLSubsystem       = 0;
dlgdata.statusString = 'Ready';
dlgdata.statusColor  = 'k';

bIsSystem = 0;
if ~isempty(options.system)
    % is it actually a system ?
    [options.system,bIsSystem] = ds_check_value(options.system,'Simulink system');
    if bIsSystem
        % no internal libs
        if any(strcmp(get_param(bdroot(options.system),'Name'),tl_get_internal_libs))
            options.system = '';
            bIsSystem = 0;
        elseif strcmp(get_param(bdroot(options.system),'BlockDiagramType'),'library')
            bSyncSignalDataEnable = 0;
        end
    else
        bSyncEnable = 0;
        dlgdata.statusString = 'The selected system does not exist.';
        dlgdata.statusColor = 'r';
        dlgdata.bIsPrepared = 0;
    end
end

if isempty(options.system)
    dlgdata.statusString = 'No Simulink system specified.';
    bSyncEnable = 0;
    dlgdata.bIsPrepared = 0;
elseif bIsSystem
    options.system = getfullname(options.system);

    % system has changed - any user libs ?
    if ~isequal(dlgdata.prevSystem,options.system)
        if bIsSystem
            dlgdata.userLibs = ds_get_related_sllibraries('system',options.system, ...
                'OmitLibs',tl_get_internal_libs);
        else
            dlgdata.userLibs = {};
        end
        libmaps = tl_find_libmaps;

        if ~isempty(dlgdata.userLibs)
            slLibraries = dlgdata.userLibs;
            for i=1:numel(dlgdata.userLibs)
                if FcnIsPrepared(slLibraries{i},libmaps)
                    slLibraries{i} = [slLibraries{i} ' (prepared)'];
                else
                    slLibraries{i} = [slLibraries{i} ' (unprepared)'];
                end
            end
            set(Children.userLibsPopup,'String',slLibraries);
        else
            set(Children.userLibsPopup,'String','(none)');
        end
        set(Children.StatusLabel,'String','Processing ...');
        [dlgdata.bIsPrepared,dlgdata.bHasSFDataObjects] = FcnIsPrepared(options.system,libmaps);
    end
end
if dlgdata.bIsPrepared
    if bIsTLSubsystem
       dlgdata.statusString = 'The system is a TargetLink subsystem.';
    else    
       dlgdata.statusString = 'The system is prepared.'; 
    end   
end        

bHasUserLibs = ~isempty(dlgdata.userLibs);

% the radio buttons
set(Children.SL2TLRadiobutton,'Value',~options.bTL2SL);
set(Children.TL2SLRadiobutton,'Value',options.bTL2SL);

% disable edit logfile button if none is specified
set(Children.logfileButton,'Enable', ...
    flag2str(exist(options.logFileName,'file')==2));
set(Children.logfileEdit,'String', ...
    options.logFileName);
set(Children.verboseCheckbox,'Value', ...
    options.bVerbose);

% scaling stuff
set(Children.syncOutputScalingDataCheckbox, ...
    'Value',options.bSyncOutputScalingData);
set(Children.syncParameterScalingDataCheckbox, ...
    'Value',options.bSyncParameterScalingData && ~options.bTL2SL, ...
    'Enable',flag2str(~options.bTL2SL));
set(Children.syncRTWDataCheckbox, ...
    'Value',options.bSyncRTWData && ~options.bTL2SL, ...
    'Enable',flag2str(~options.bTL2SL));
set(Children.syncSignalScalingDataCheckbox, ...
    'Enable',flag2str(bSyncSignalDataEnable), ...
    'Value',options.bSyncSignalScalingData && bSyncSignalDataEnable);
set(Children.syncSaturationFlagsCheckbox, ...
    'Value',options.bSyncSaturationFlags);
set(Children.syncConstrainedLimitsCheckbox, ...
    'Value',options.bSyncConstrainedLimits);

% SF data
set(Children.syncSFCompiledDataCheckbox, ...
    'Enable',flag2str(bSyncSignalDataEnable && dlgdata.bHasSFDataObjects), ...
    'Value',options.bSyncSFObjectCompiledScalingData && bSyncSignalDataEnable && dlgdata.bHasSFDataObjects);
set(Children.syncSFScalingDataCheckbox, ...
    'Enable',flag2str(dlgdata.bHasSFDataObjects), ...
    'Value',options.bSyncSFObjectScalingData && dlgdata.bHasSFDataObjects);

set(Children.syncLibsCheckbox, ...
    'Value',options.bSyncLibs && bHasUserLibs, ...
    'Enable',flag2str(bHasUserLibs));
set(Children.syncLibraryButton, ...
    'Enable',flag2str(bHasUserLibs));
set(Children.syncSystemButton, ...
    'Enable',flag2str(bSyncEnable));
set(Children.systemEdit, ...
    'string',options.system, ...
    'ForeGroundColor',dlgdata.statusColor);

% controls for library processing
set([ ...
    Children.userLibsPopup ...
    Children.verboseLibCheckbox ...
    Children.syncLibOutputScalingDataCheckbox ...
    Children.syncLibParameterScalingDataCheckbox ...
    Children.syncLibRTWDataCheckbox ...
    Children.syncLibraryButton ...
    Children.syncLibSaturationFlagsCheckbox ...
    Children.syncLibConstrainedLimitsCheckbox ...
    Children.syncLibSFScalingDataCheckbox], ...
    'Enable',flag2str(bHasUserLibs));
set(Children.verboseLibCheckbox, ...
    'Value',libOptions.bVerbose && bHasUserLibs);
set(Children.syncLibOutputScalingDataCheckbox, ...
    'Value',libOptions.bSyncOutputScalingData && bHasUserLibs);
set(Children.syncLibParameterScalingDataCheckbox, ...
    'Value',libOptions.bSyncParameterScalingData && bHasUserLibs);
set(Children.syncLibRTWDataCheckbox, ...
    'Value',libOptions.bSyncRTWData && bHasUserLibs);
set(Children.syncLibSaturationFlagsCheckbox, ...
    'Value',libOptions.bSyncSaturationFlags && bHasUserLibs);
set(Children.syncLibConstrainedLimitsCheckbox, ...
    'Value',libOptions.bSyncConstrainedLimits && bHasUserLibs);
set(Children.syncLibSFScalingDataCheckbox, ...
    'Value',libOptions.bSyncSFObjectScalingData && bHasUserLibs);

% the label is used to display warnings and infos
set(Children.StatusLabel, ...
    'String',dlgdata.statusString, ...
    'ForeGroundColor',dlgdata.statusColor);

% toolbar buttons
set(Children.Propman, ...
    'Enable',flag2str(bIsSystem));

% save user data
dlgdata.prevSystem = options.system;
dlgdata.options = options;
dlgdata.libOptions = libOptions;
set(dlgfig,'UserData',dlgdata);
set(dlgfig,'Pointer','arrow');

% move to front
figure(dlgfig);

%================================================================================
% Function opens file dialog that can be used to select a Simulink system.
%
% Output parameters
%
% modelName     the name of the model that has been selected
% bModified     1 if a valid model has been selected, 0 otherwise
%================================================================================
function [modelName,bModified] = FcnBrowse

% defaults
bModified = 0;
[modelName, directory] = uigetfile('*.mdl','Select a Simulink model');

if ~isequal(modelName,0) && ~isequal(directory,0)
    % a file has been selected
    % is it *.mdl ?
    [tmp, modelName, ext]  = fileparts(modelName); %#ok
    if strcmpi('.mdl',ext) == 0
        ds_error_msg( ...
            ['"' modelName ext '" is not a Simulink model file.'], ...
            'Title','Not a Simulink file', ...
            'PrintMessage','no', ...
            'RegisterMessage', 'no');
    elseif exist(modelName,'file') ~= 4  % must reside on search path
        ds_error_msg( ...
            ['"' modelName '" does not reside on MATLAB''s search path.'], ...
            'Title','Model is unknown to Simulink', ...
            'PrintMessage','no', ...
            'RegisterMessage', 'no');
    elseif any(strcmp(modelName,tl_get_internal_libs))
        ds_error_msg( ...
            ['"' modelName '" is a TargetLink library and can not be prepared.'], ...
            'Title','TargetLink library selected', ...
            'PrintMessage','no', ...
            'RegisterMessage', 'no');
    else    
        try
            % open the model
            open_system(modelName);
            bModified = 1;
        catch
            ds_error_msg( ...
                ['"' modelName '" is not a valid Simulink model.'], ...
                'Title','Not a model', ...
                'PrintMessage','no', ...
                'RegisterMessage', 'no');
        end

        % check if the selected model is a simulink system
        if bModified
            [modelName, bModified] = ds_check_value(modelName,'Simulink system');
            if ~bModified
                ds_error_msg( ...
                    ['"' modelName '" is not a Simulink system.'], ...
                    'Title','Not a model', ...
                    'PrintMessage','no', ...
                    'RegisterMessage', 'no');
            else
                modelName = getfullname(modelName);
            end
        end
    end
end

%================================================================================
% Function checks if a subsystem, model or library is prepared.
%
% Input parameters
%   system      system to be checked
%   libmaps     libmaps
%
% Output parameters
%   bIsPrepared    1 if there are no unenhanced blocks, nor blocks that
%                  must be replaced, nur unsupported blocks
%   bHasSFDataObjects
%                  1 if there are SF data objects
%================================================================================
function [bIsPrepared,bHasSFDataObjects] = FcnIsPrepared(system,libmaps)

options.system = system;
options.bVerbose      = 0;
options.bCompileModel = 0;
options.bCheckLibLink = 0;
options.bPrepareLibBlocks = 0;
options.libmaps = libmaps;
options.mode = 2;

bs = tl_check_system(options);
bIsPrepared = isempty(bs.hRepBlocks) && isempty(bs.hUnEnhBlocks) && isempty(bs.unPreparedLibs) && ...
    isempty(bs.hUnEnhInports) && isempty(bs.hUnEnhOutports) && isempty(bs.hUnSupBlocks);
bHasSFDataObjects = ~isempty(bs.hSFDataObjects);

%================================================================================
% Function starts model preparation.
%
% Input parameters
%   dlgfig      dialog handle
%   dlgdata     dislog user data
%   options     preparation options
%
%================================================================================
function FcnSync(dlgfig,dlgdata,options,bIsSystem)

set(dlgfig,'Pointer','watch');
params = struct2cell(options);
set(dlgdata.children.StatusLabel','String','Processing ...');
fields = fieldnames(options);
bVerbose = options.bVerbose;

% try to open system
if ~ds_isa(options.system,'slblock') && ~isempty(options.system) && ischar(options.system)
    try
        open_system(strtok(options.system,'/'));
    catch
        % open failed - this is intercepted in tl_sync_system
    end    
end    

% remove boolean b in front of fieldname
for i=1:numel(fields)
    if fields{i}(1) == 'b'
        fields{i} = fields{i}(2:end);
    end
end

options = [fields' ; params'];

    
if bVerbose
    disp('Invoking tl_sync_system:');
    disp('tl_sync_system( ...');
    for i=1:2:numel(options)
        fprintf('    ''%s'', %s, ...
',options{i},ds_var2str(options{i+1}));
    end
    disp('    );');
end

options = tl_sync_system(options{:});
if bVerbose
    disp(' ... done!');
end

% update system in case its name has been modified
if bIsSystem && ds_isa(options.system,'slblock')
    dlgdata.options.system = getfullname(options.system);
end

% enforce update of controls
dlgdata.prevSystem = '';
FcnUpdate(dlgfig,dlgdata);
set(dlgfig,'Pointer','arrow');


